import { FormulaError } from './formula-error';
import { 
    TAllTypes, 
    IValue,
    IValueNumber,
    IValueString
} from  './types'
export function typeofValue(val: TAllTypes) {
    if(val.type === 'value') {
        return val.dataType;
    }
    return 'notValue';
}
export function isEqualVal(v1: IValue, v2: IValue) {
    if(v1 == v2) {
        return true;
    }
    if(v1.dataType === v2.dataType) {
        return v1.value === v2.value;
    }
    if((v1.dataType === 'string' || v1.dataType === 'number') && (v2.dataType === 'string' || v2.dataType === 'number')) {
        return String(v1.value) === String(v2.value);
    }
    return false;
}

export function parseToNumber(val: IValueNumber | IValueString): IValueNumber {
    if(val.type === 'value' && val.dataType === 'number') {
        return val as IValueNumber;
    }
    if(val.type === 'value' && val.dataType === 'string') {
        let _val = Number(val.value);
        if(isNaN(_val)) {
            return {
                type: 'value',
                dataType: 'number',
                value: 0
            }
        } else {
            return {
                type: 'value',
                dataType: 'number',
                value: _val
            }
        }
    }
    return {
        type: 'value',
        dataType: 'number',
        value: 0
    }
}
export function transformBaseValueToFormulaValue(val: null|string|number|boolean): IValue {
    if(val === null) {
        return {
            type: 'value',
            dataType: 'string',
            value: ''
        }
    }
    if(typeof val === 'boolean') {
        return {
            type: 'value',
            dataType: 'boolean',
            value: val
        }
    }
    if(typeof val === 'number') {
        return {
            type: 'value',
            dataType: 'number',
            value: val
        }
    }
    if(typeof val === 'string') {
        return {
            type: 'value',
            dataType: 'string',
            value: val
        }
    }
    return {
        type: 'value',
        dataType: 'string',
        value: ''
    }
}
export const safeWhile = (func: (idx: number) => boolean, max = 1000) => {
    let idx = 0;
    while(true) {
        let manualBreck = func(idx);
        if(idx++ === max || manualBreck) {
            break;
        }
    }
}
const equalConditionReg = /^(>=|<=|>|<|=|!){1}/g;
export function isEqualCondition(_val: IValue, condition: string): boolean {
    if(typeof condition !== 'string' || !_val) {
        throw new FormulaError('#UNKOWN!', {errorId: 'e5bd7fc099c0'})
    }
    let val = (_val.type === 'value' && _val.dataType === 'string' && !isNaN(Number(_val.value))) ? parseToNumber(_val) : _val;
    let matchRes = condition.match(equalConditionReg);
    if(matchRes !== null) {
        let conditionSymbol = matchRes[0];
        let targetVal = condition.replace(conditionSymbol, '');
        if(conditionSymbol === '>') {
            if(val.type === 'value' && val.dataType === 'number' && !isNaN(Number(targetVal))) {
                return val.value > Number(targetVal)
            }
            return false;
        }
        if(conditionSymbol === '<') {
            if(val.type === 'value' && val.dataType === 'number' && !isNaN(Number(targetVal))) {
                return val.value < Number(targetVal)
            }
            return false;
        }
        if(conditionSymbol === '>=') {
            if(val.type === 'value' && val.dataType === 'number' && !isNaN(Number(targetVal))) {
                return val.value >= Number(targetVal)
            }
            return false;
        }
        if(conditionSymbol === '<=') {
            if(val.type === 'value' && val.dataType === 'number' && !isNaN(Number(targetVal))) {
                return val.value <= Number(targetVal)
            }
            return false;
        }
        if(conditionSymbol === '=') {
            if(val.type == 'value' && (val.dataType === 'number' || val.dataType === 'string')) {
                return val.value.toString() === targetVal;
            }
            return false;
        }
        if(conditionSymbol === '!') {
            if(val.type == 'value' && (val.dataType === 'number' || val.dataType === 'string')) {
                return val.value.toString() !== targetVal;
            }
            return true;
        }
    } else {
        if(val.type == 'value' && (val.dataType === 'number' || val.dataType === 'string')) {
            return val.value.toString() === condition;
        }
        return false;
    }
}

export function isPositionValue(val: TAllTypes) {
    return val.type === 'position' || val.type === 'rowPosition' || val.type === 'colPosition';
}